package org.github.latex.web;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.digest.Md5Crypt;
import org.apache.commons.io.Charsets;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.github.latex.ExternalProgram;
import org.github.latex.LatexConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.ExecutionException;

@Controller
public class LatexController {

    private final static Charset CHARSET = Charsets.toCharset("utf-8");

    private final Logger log = LoggerFactory.getLogger("latex-server");

    @Resource
    private LatexConfig config ;

    private String dataDir ;

    private String tpl ;


    @PostConstruct
    public void init() throws IOException {
        if(StringUtils.isEmpty(config.getLatexPath())){
            Process process = Runtime.getRuntime().exec("which latex");
            config.setLatexPath(IOUtils.toString(process.getInputStream(),"utf-8").trim());
        }

        if(StringUtils.isEmpty(config.getConvertPath())){
            Process process = Runtime.getRuntime().exec("which dvisvgm");
            config.setConvertPath(IOUtils.toString(process.getInputStream(),"utf-8").trim());
        }

        org.springframework.core.io.Resource latexTpl = new ClassPathResource("latex.tpl");
        tpl = IOUtils.toString(latexTpl.getInputStream(),CHARSET);

        dataDir = config.getDataDir() ;

        if(!dataDir.endsWith("/")){
            dataDir +="/";
        }
    }

    @RequestMapping(value = {"/"})
    public String index( ){
        return "index";
    }


    @RequestMapping(value = {"/equation"},produces="image/svg+xml" )
    @ResponseBody
    public byte[] equation(@RequestParam(value = "preview" , defaultValue = "false")boolean preview , @RequestParam("tex") String tex ) throws IOException, InterruptedException {

        if(StringUtils.isEmpty(config.getLatexPath()) || StringUtils.isEmpty(config.getConvertPath())){
            return createError("check latex & convert path");
        }

        long start = System.currentTimeMillis();


        String expression = tex ;

        expression = expression.trim();

        String expressionHash = DigestUtils.md2Hex(expression.getBytes("utf-8"));

        log.info("expression:{},hash:{}" ,expression ,expressionHash );

        String workDir = dataDir + expressionHash ;

        File workDirFile = new File(workDir);
        if(!workDirFile.exists()){
            workDirFile.mkdirs();
        }

        File svgFile  = new File(workDir +"/latex.svg");

        if( !preview && svgFile.exists() ){
            return FileUtils.readFileToByteArray(svgFile) ;
        }


        System.err.println("step init :" + (System.currentTimeMillis() - start ));
        start = System.currentTimeMillis();
        File texFile = new File( workDir + "/latex.tex");

        FileUtils.write(texFile,tpl.replace("#expression#" , swap(expression) ),"utf-8");

        String cmdOfLatex = String.format("%s -interaction=nonstopmode latex.tex " ,config.getLatexPath() ) ;
        new ExternalProgram(cmdOfLatex,workDirFile).run();

        System.err.println("step 1 :" + (System.currentTimeMillis() - start ));
        start = System.currentTimeMillis();

        File errorFile = new File(workDir + "latex.err");
        if(errorFile.exists()){
            String error = FileUtils.readFileToString(errorFile ,"utf-8");
            if(!StringUtils.isEmpty(error)){
                return createError(error);
            }
        }

        String cmdOfConvert = String.format("%s  -n latex.dvi" ,config.getConvertPath() ) ;
        new ExternalProgram(cmdOfConvert,workDirFile).run();
        System.err.println("step 2 :" + (System.currentTimeMillis() - start ));

        if(svgFile.exists()){
            return FileUtils.readFileToByteArray(svgFile);
        }else{
            return createError("The input equation is illegal");
        }

    }

    public static String swap( String expression ){

        /*expression  = expression.replaceAll("(\\\\\\w+\\{)","@$1");
        StringBuilder sb = new StringBuilder();
        int leftBrace  = 0 ;
        for(int i = 0 ; i < expression.length() ; i++ ){
            char c  =  expression.charAt(i );
            if(c == '@' && i + 1 < expression.length() && expression.charAt( i + 1) == '\\' )  {
                if(leftBrace == 0 ){
                    sb.append("$\\displaystyle ");
                }
            }else{
                sb.append(c);
                if(c  == '{'){
                    leftBrace++ ;
                }else  if( c == '}'){
                    leftBrace-- ;

                    if(leftBrace == 0 ){
                        sb.append(" $");
                    }
                }
            }
        }*/
        return expression ;
    }


    public static byte[] createError(String text ) {
        return ("<?xml version='1.0' encoding='UTF-8'?>\n" +
                "<svg xmlns=\"http://www.w3.org/2000/svg\"   >\n" +
                "    <text x=\"10\" y=\"10\">"+text+"</text>\n" +
                "</svg>").getBytes(CHARSET);
    }

    public static void main(String[] args) throws IOException, ExecutionException, InterruptedException {

        //Process process = new ProcessBuilder().command("/usr/local/texlive/2017/bin/x86_64-linux/xelatex  ./latex.tex").directory(new File("/home/wens/dev/latexserver/data/93be8a4bd7fb79df5076c8200c6014f0")).start();

        //Runtime.getRuntime().exec( ,null ,new File("/home/wens/dev/latexserver/data/93be8a4bd7fb79df5076c8200c6014f0") );

        ExternalProgram externalProgram = new ExternalProgram("/usr/local/texlive/2017/bin/x86_64-linux/xelatex  -interaction=nonstopmode   latex.tex", new File("/home/wens/dev/latexserver/data/93be8a4bd7fb79df5076c8200c6014f0"));

        long s  = System.currentTimeMillis();
        String run = externalProgram.run();

        System.out.println(System.currentTimeMillis() - s );

        //System.out.println(run);

        System.exit(0);


    }



}
